Programming

  • preprocessor - Which preprocessor symbols should be used?
  • include files - Where are the right include files?
  • libnsl libsocket - Where's the socket code? rpc? xdr?
  • libdl - Global symbols in dlopen attachments
  • regular expressions - Where's regex?
  • namelist - Where's nlist?
  • /proc - Using /proc instead of ptrace
  • mutex - What is the mutual exclusion library
  • bcopy/bzero/bcmp - What to use instead of bcopy, bzero, bcmp
  • index/rindex - What to use instead of index, rindex
  • strcasecmp - Can I use strcasecmp
  • getwd - What to use instead of getwd
  • getdtablesize - What to use instead of getdtablesize
  • setjmp/longjmp - How to use setjmp/longjmp
  • gethostname - What to use instead of gethostname
  • gethostid - What to use instead of gethostid
  • getpagesize - What to use instead of getpagesize
  • pseudo-ttys - How to open a pseudo-tty
  • termios - Using termios Routines
  • ltchars - Where are ltchars defined?
  • IEEE math - Do I need to use IEEE math?
  • signals - How to use signals?
  • wait - Waiting for children to exit
  • timing - Timing programs, or HZ is undefined
  • gettimeofday - Gettimeofday takes only one argument
  • shadow - Shadow password file
  • null pointers - Dereferencing NULL pointers
  • mnttab - /etc/mtab or /etc/mnttab?
  • vfstab - /etc/fstab or /etc/vfstab?
  • ref/def - Multiply defined global symbols
  • stat - Using stat/fstat/lstat
  • mknod - Using mknod
  • Which preprocessor symbols should be used?

    There is no simple answer to this question, and is best left to the internal coding conventions of each software developer.

    Here are some possible guidelines:

    For high-level standard definitions, there are some commonly used symbols which may be useful in porting. Such defines are used to select major functionality sets based on the heritage of the target operating system. For example, SVR4, SYSV, BSD43 and OSF1 are often used. The appropriate symbol for the MIPS ABI would be SVR4. This symbol is not automatically defined on the Reference Platform, and should be defined in the Makefile.

    For standards such as ANSI C, POSIX, and X/Open, the appropriate symbols are __STDC__, _POSIX_SOURCE, _XOPEN_SOURCE. Appropriate defines and values for these are supplied by the compiler on the Reference Platform. The IRIX Reference Platform also introduces the private symbol _ABI_SOURCE, which is automatically defined when the abicc script is used for compilation. This symbol is used to select functionality from system header files.

    Fine-grained feature tests can be used for specific features of interest. To illustrate the techniques, the missing index string routine can either be selected at an operating system functionality level:

    #ifdef SVR4 #define index(s, c) strchr((s), (c)) #endif Or at a feature level:

    #ifdef HAVE_STRCHR #define index(s, c) strchr((s), (c)) #endif It may be useful to use the operating system-level define to select the feature-level define, as follows: #ifdef SVR4 #define HAVE_STRCHR #endif . . . #ifdef HAVE_STRCHR #define index(s, c) strchr((s), (c)) #endif

    Where are the right include files?

    On the IRIX Reference Platform, the includes files for ABI programming are simply in /usr/include, with the exception of the OSF/Motif include files, which are in /usr/include/abi. The proper sections of the standard include files are selected when _ABI_SOURCE is defined. The abi specific include files are selected when -abi is given to the compiler. Both are selected automatically when abicc is used (the preferred compilation method).

    On the Reference Platform for the 1.0 Conformance Guide (RISC/os 5.01), the include files are those from the SVR4 environment, /svr4/usr/include. These are selected automatically when /svr4/bin/cc is used for compilation.

    Where's the socket Code? rpc? xdr?

    Many of the network functions and definitions that were present in the BSD libc are now in libsocket.so. Programs which use socket-based networking services will need to be linked with -lnsl -lsocket. The socket library is actually emulation code built on top of services provided by the network services library (libnsl) so it is not generally possible to specify just -lsocket.

    Programs which use the X11 and Motif interfaces will need to link with these libraries.

    WARNING: the ABI requires that programs which use dynamic shared objects specify them on the link line so that they appear in the dependency list. Do not count on ABI libraries having built-in dependencies. These dependencies may differ on different platforms, so a program may work on one because the dependency is supplied "invisibly", then fail on others. Use elfdump -Dl on the IRIX Reference Platform to check the library list (ldd may be appropriate on some other platforms). NOTE: the socket emulation code does not always provide exactly equivalent functionality to native sockets. Routines such as gethostbyname may have different behavior; in particular, gethostbyname differs in that it only returns information from the /etc/hosts file, it does not access NIS or the nameserver.

    The rpc and xdr routines are libnsl, and the old rpcsvc library is no longer present.

    Global symbols in dlopen attachments

    Objects loaded by a call to dlopen can, in general, not access objects loaded by a different call to dlopen. A provision for making symbols in a dlopen attached object global will be introduced with the 1.2 Conformance Guide, where the RTLD_GLOBAL flag can be or'd with the mode argument to dlopen. Until the RTLD_GLOBAL functionality is implemented, dlsym should be used to indirectly reference the symbols. For example, if routine sub2 in module mod2 wants to call routine sub1 in mod1, one (simple-minded) way to make that work would be as follows:

    dltest.c:

    void *dlhandle1, *dlhandle2; int (*sub1_ptr)(int); . . . /* open objects */ dlhandle1 = dlopen ("mod1.o", RTLD_NOW); dlhandle2 = dlopen ("mod2.o", RTLD_NOW); /* find address of function */ if (*sub1_ptr = NULL) sub1_ptr = (int (*)())dlsym (dlhandle1, "sub1"); (void) sub2 (); mod1.c: /* define routine sub1() */ int sub1 (int arg); int sub1 (int arg) { printf ("This is a test of sub1 (arg %d)\n", arg); return 1; } mod2.c: /* call routine in different dlopen() attachment */ #include #define CALL_ARG 10 extern int (*sub1_ptr)(int); void sub2() { int rv = 0; if (*sub1_ptr != NULL) rv = (*sub1_ptr)(CALL_ARG); else printf ("routine not mapped\n"); } When RTLD_GLOBAL is available, care should be taken not to overuse it. There are benefits to not having to worry about namespace conflicts, if symbols in DSOs in general are kept private, a DSO can be developed with less constraints, for example, when multiple groups are developing DSOs for a large product set and don't want to have to coordinate a "global namespace".

    Another note about the above. The symbols contained in the original a.out and the objects loaded at program startup with the a.out are not available to dlsym, since they are directly available. If dlsym needs to access all the symbols in the aggregate symbol table, the ones from the a.out and objects loaded with the a.out at startup can be made available by making a call to dlopen with the pathname argument set to 0.

    Where's regex?

    The regexp functions (see regexpr(3G)) are not defined in libc, as they are on some UNIX implementations. Under the MIPS ABI, you must link with libgen.a (-lgen) in order to get these definitions.

    NOTE: the libgen.a library is not specified by the ABI, but applications are free to link it in in their build. This is discussed in on-site linkage. libgen.a will be included in revision 1.2 of the Conformance Guide.

    Where's nlist?

    The nlist routine is in a library not specified by the ABI, and should be avoided. On IRIX and some other platforms it is found in libmld, on the rest it is found in libelf.

    Using /proc Instead of ptrace.

    Programs should use the /proc interface in preference to the ptrace routines to examine running programs. The ptrace routines are not standardized.